package com.lagou.edu.factory;

import com.alibaba.druid.util.StringUtils;
import com.lagou.edu.annotation.MyAutowired;
import com.lagou.edu.annotation.MyService;
import com.lagou.edu.annotation.MyTransactional;
import org.reflections.Reflections;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


public class BeanFactory {

    // 存储对象
    private static Map<String,Object> map = new HashMap<>();


    private static BeanFactory beanFactory = new BeanFactory();

    //单利模式beanFactory
    private BeanFactory(){
    }

    public static BeanFactory getInstance(){
        return beanFactory;
    }


    static{
        try{
            //扫描包，分析需实例化的对象列表（service和事务管理器）,通过反射技术实例化对象并且存储待用（map集合）
            //扫描获取反射对象集合
            Reflections f = new Reflections("com.lagou.edu");
            //获取注解为service的集合
            Set<Class<?>> set = f.getTypesAnnotatedWith(MyService.class);
            for (Class<?> c : set) {
                System.out.println(c.getName());
                Class<?> bean=Class.forName(c.getName());
                System.out.println(bean.newInstance());
                // 通过反射技术实例化对象
                MyService annotation = c.getAnnotation(MyService.class);
                //对象ID在service注解有value时用value，没有时用类名
                if(StringUtils.isEmpty(annotation.value())){
                    //由于getName获取的是全限定类名，所以要分割去掉前面包名部分
                    String[] names = c.getName().split("\\.");
                    map.put(names[names.length-1], bean.newInstance());
                }else{
                    map.put(annotation.value(), bean.newInstance());
                }
            };
            for(Map.Entry<String, Object> a:map.entrySet()){
                System.out.println("对象"+a.getKey());
                Object bean= a.getValue();
                Class<?> c =bean.getClass();
                //获取属性集合
                Field[] fields = c.getDeclaredFields();
                //遍历属性，若持有Autowired注解则注入
                for (Field field : fields) {
                    if (field.isAnnotationPresent(MyAutowired.class)
                            &&field.getAnnotation(MyAutowired.class).value()) {
                        String name = field.getName();
                        System.out.println("antowire属性名"+name);
                        //开启访问权限
                        field.setAccessible(true);
                        //为该属性注入值
                        Object paramObject=map.get(name);
                        field.set(bean, paramObject);
                    }
                }
                //判断对象类是否持有Transactional注解，若有则修改对象为代理对象
                if(c.isAnnotationPresent(MyTransactional.class)){
                    //获取代理工厂
                    ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
                    //判断对象是否实现接口
                    //获取类c实现的所有接口
                    Class[] face = c.getInterfaces();
                    if(face!=null&&face.length>0){
                        //实现使用JDK
                        bean = proxyFactory.getJdkProxy(bean);
                    }else{
                        //没实现使用CGLIB
                        bean = proxyFactory.getCglibProxy(bean);
                    }
                }
                // 把处理之后的object重新放到map中
                map.put(a.getKey(),bean);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    public static Object getBean(String id){
        return map.get(id);
    }
}


